import java.util.Objects;
import java.util.Scanner;

/**
 * @author 刘齐山
 * @version 1.0
 */

public class CheckPoint {
    public static void main(String[] args) {
       boolean continu;             //打印欢迎菜单
        menu(1);
        do {
            int[] checkPointAndCitizen= scanLocationOfCitizen();              //输入检测点个数和市民位置
            int x = checkPointAndCitizen[0];                                  //存入检测点个数
            int[] citizen ={checkPointAndCitizen[1],checkPointAndCitizen[2]}; //存入市民位置
            int[][] location= scanLocationOfCheckPoint(x);                    //输入检测点位置
            printResult(location,citizen,x);                                  //计算并打印结果
            continu = menu(2);    //打印循环菜单
        }while (continu);           //当选择继续时
        menu(3);                 //打印再见菜单
    }

    /**
     * 输入检测点个数和市民位置
     * @return 检测点个数和市民位置的数组
     */
    public static int[] scanLocationOfCitizen(){
        int[] checkPointAndCitizen = new int[3];
        boolean judge;

        do {
            System.out.println("注意:1.数据之间用空格隔开。");
            System.out.println("    2.所有数据必须都为整数。");
            System.out.println("    3.检测点个数至少为3个。");
            System.out.println("    4.若数据没有输入完毕，请继续输入。");
            System.out.println("    5.第四个及以后的数据不会被读取到。");
            System.out.print("请分别输入检测点个数和市民位置坐标的x,y值:");
            Scanner in = new Scanner(System.in);

            for(int i = 0;; i++){
               //判断输入的是否为整型
                if (in.hasNextInt()) {
                    checkPointAndCitizen[i] = in.nextInt();
                    //当三个整型数据录入后 判断检测点个数是否大于等于3且小于等于200
                    if (i==2 && (checkPointAndCitizen[0]<3 || checkPointAndCitizen[0]>200)){
                        System.out.println("*检测点个数必须大于等于3且小于等于200,请从新输入！*");
                        System.out.println("--------------------------------------------------");
                        judge = false;
                        break;
                    }
                    //当三个整型数据录入后 判断市民坐标的xy值的绝对值是否小于等于1000
                    if (i==2&&(Math.abs(checkPointAndCitizen[1])>1E3 || Math.abs(checkPointAndCitizen[2])>1E3)){
                        System.out.println("*市民坐标的xy值的绝对值不能大于1000,请从新输入！*");
                        System.out.println("--------------------------------------------------");
                        judge = false;
                        break;
                    }
                }
                //若输入不为整型数据
                else {
                    System.out.println("*输入的数据必须为整数,请从新输入！*");
                    System.out.println("--------------------------------------------------");
                    judge = false;
                    break;
                }
                //判断并提示是否录入完毕
                if(i==2){
                   System.out.println("录入成功!");
                   System.out.println("有"+checkPointAndCitizen[0]+"个检测点，市民位置为("+checkPointAndCitizen[1]+","+checkPointAndCitizen[2]+")");
                   System.out.println("--------------------------------------------------");
                   judge = true;
                   break;
                }
            }
        }while (!judge);
        return checkPointAndCitizen;
    }


    /**
     * 输入检测点位置
     * @param a 检测点个数
     * @return 检测点位置的数组
     */
    public static int[][] scanLocationOfCheckPoint(int a) {
        int i, j;
        int[][] checkPoint = new int[a][2];
        boolean judge1 = false;
        boolean judge2 = true;
        System.out.println("现在开始录入检测点位置");
        System.out.println("注意:1.数据之间用空格隔开且都为整数");
        System.out.println("    2.若数据没有输入完毕，请继续输入。");
        System.out.println("    3.第三个及以后的数据不会被读取到。");
        System.out.println("    4.所有检测点位置坐标的xy值的绝对值不能大于1000。");
        for (i = 0; i < a; i++) {
            for (;;){
                int n=i+1;              //标号
                System.out.print("请分别输入第" +n+ "个检测点的位置坐标的x，y值：");//打印提示
                Scanner in = new Scanner(System.in);
                //二维下标循环
                for (j = 0;j<2; j++) {
                    //判断是否为整型
                    if (in.hasNextInt()) {
                        checkPoint[i][j] = in.nextInt();
                        //如果输入的坐标值绝对值大于1000
                        if (Math.abs(checkPoint[i][j]) > 1E3) {
                            System.out.println("*所有检测点位置坐标的xy值的绝对值不能大于1000，请重新输入！*");
                            if (i>0)
                                i--;
                            judge2 = false;
                            break;
                        }
                        //当一个检测点的xy输入完毕后
                        if (j==1) {
                            //如果不是录入的第一个检测点的位置坐标
                            if (i > 0) {
                                //循环遍历对比 是否和已有检测点位置坐标相同
                                for (int m = 0; m < i; m++) {
                                    //如果匹配到已有的数据
                                    if (checkPoint[i][0] == checkPoint[m][0] && checkPoint[i][1] == checkPoint[m][1]) {
                                        int rank = m+1;
                                        System.out.println("*与第"+rank+"个检测点位置坐标重复，请重新输入!*");
                                            i--;
                                        judge2 = false;
                                        break;
                                    }else {
                                        judge2 = true;
                                    }
                                }
                            }

                            //如果检测完没有和已有的数据匹配
                            if (judge2) {
                                System.out.println("录入成功!");
                                judge1 = true;
                                break;
                            }
                        }
                    }
                    //如果输入的不是整型
                    else {
                        System.out.println("*输入的数据必须为整数,请重新输入！*");
                        if (i!=0){
                            i--;
                        }
                        break;
                    }
                }
                //如果第i+1号检测点的位置坐标录入成功
                if (judge1)
                    break;
            }
        }
        System.out.println("--------------------------------------------------");
        return checkPoint;
        }

    /**
     * 求距离
     * @param x 检测点距离
     * @param location 检测点位置
     * @param citizen 市民位置
     * @return 各个检测点对应距离的数组
     */
    public static double[] calculationOfdDistance(int[][]location,int[]citizen,int x){
        double[] distance = new double[x];
        for (int i = 0;i<x;i++){
            double sum = ((location[i][0]-citizen[0])*(location[i][0]-citizen[0]))+((location[i][1]-citizen[1])*(location[i][1]-citizen[1]));
            distance[i] = Math.pow(sum,1.0/2);
        }
        return distance;
    }

    /**
     *比较距离并返回下标
     * @param x 检测点个数
     * @param distance 距离数组
     * @return 最小的三个距离对应的检测点位置下标的数组
     */
    public static int[] comparisonOfDistance(double[] distance,int x){
        //寻找最大距离检测点位置的下标
        int indexOfMax =0;
        for (int i=0;i<x;i++){
            //在该距离大于indexOfMax距离 或者 在两者距离相等的情况下i比indexOfMax大
            if (distance[i]>distance[indexOfMax]||(i>indexOfMax&&distance[i]==distance[indexOfMax])){
                indexOfMax=i;
            }
        }
        //初始化为最大距离的下标
        int first=indexOfMax,second=indexOfMax,third=indexOfMax;
        //遍历寻找最小的三个距离的下标
        for (int i = 0; i < x; i++){
                //如果该距离小于first距离 或者 在两者距离相等的情况下i比first小 时
                if (distance[first]>distance[i]||(distance[first] == distance[i] && i<first)){
                    third = second;
                    second = first;
                    first = i;
                }
                //如果该距离小于second距离 或者 在两者距离相等的情况下i比second小 时
                else if (distance[second]>distance[i]||(distance[second] == distance[i] && i<second)){
                    third =second;
                    second = i;
                }
                //如果该距离小于third距离 或者 在两者距离相等的情况下i比third小 时
                else if (distance[third]>distance[i]||(distance[third] == distance[i] && i<third)){
                    third = i;
                }
        }
        //把三个下标存入一个数组并返回
        int[] indexOfDistance = new int[3];
        indexOfDistance[0] = first;
        indexOfDistance[1] = second;
        indexOfDistance[2] = third;
        return indexOfDistance;
    }

    /**
     *打印结果
     */
    public static void printResult(int[][]location,int[]citizen,int x){
        double[] distance = calculationOfdDistance(location,citizen,x);     //求所有检测点距离并存入数组返回
        int[]index = comparisonOfDistance(distance,x);                      //比较距离得到前三下标并存入数组返回
        //把下标数组分别+1 变成编号数组
        int[] rank = {index[0]+1,index[1]+1,index[2]+1};
        System.out.println("最近的检测点为第"+rank[0]+"个检测点，位置为:("+location[index[0]][0]+","+location[index[0]][1]+")");
        System.out.println("其次的检测点为第"+rank[1]+"个检测点，位置为:("+location[index[1]][0]+","+location[index[1]][1]+")");
        System.out.println("第三近的检测点为第"+rank[2]+"个检测点，位置为:("+location[index[2]][0]+","+location[index[2]][1]+")");
    }

    /**
     * 菜单
     * @param a 菜单选择
     */
    public static boolean menu(int a){
        boolean continu = true;
        switch (a) {
            //欢迎菜单
            case 1 -> {
                System.out.println("*******************欢迎使用本程序*******************");
                System.out.println("本程序可以根据您输入的位置帮您找到离您最近的三个核酸检测点。");
                System.out.println("--------------------------------------------------");
            }
            //询问是否继续菜单
            case 2 -> {
                String x;
                do {
                    System.out.println("--------------------------------------------------");
                    System.out.println("是否继续使用本程序？(y/n)");
                    Scanner in = new Scanner(System.in);
                    x = in.next();
                } while (!Objects.equals(x, "y") && !Objects.equals(x, "Y") && !Objects.equals(x, "n") && !Objects.equals(x, "N"));
                continu = x.equals("y") || x.equals("Y");
                if (continu)
                    System.out.println("--------------------------------------------------");
            }
            //再见菜单
            case 3 -> System.out.println("感谢使用本程序，期待您的再次使用！ 再见~");
        }
    return continu;
    }
}





